<?php declare(strict_types=1);

namespace App\Util;

use App\Models\OrderGoodsDetail;
use Illuminate\Support\Facades\Log;

class ExeclUtil
{

    public function loadGoods(\Generator $orders, string $key = "goods")
    {
        $bufferSize = 2; // 每批处理 2 个订单（示例值，可调整）
        $buffer = [];
        $out_trade_no_arr = [];
        foreach ($orders as $order) {
            // 将订单加入缓冲区
            $buffer[] = $order;
            $out_trade_no_arr[] = $order->out_trade_no;
            // 当缓冲区满时处理
            if (count($out_trade_no_arr) >= $bufferSize) {
                // 批量查询关联数据
                $orderItems = OrderGoodsDetail::query()
                    ->whereIn("out_trade_no", $out_trade_no_arr)
                    ->get()
                    ->keyBy("out_trade_no") // 直接使用 Eloquent 的 keyBy 方法
                    ->toArray();
                // 挂载数据并 yield 订单
                foreach ($buffer as $bufferedOrder) {
                    $bufferedOrder->$key = $orderItems[$bufferedOrder->out_trade_no] ?? []; // 安全访问
                    yield $bufferedOrder;
                }
                // 重置缓冲区
                $buffer = [];
                $out_trade_no_arr = [];
            }
        }
    }

    public function generatorExport(string $filePath, string $fileName, $title, \Generator $orders, callable $callable): void
    {
        if (!is_dir($filePath)) {
            mkdir($filePath, 0777, true);
        }
        $file = $filePath . $fileName;
        $fileObj = fopen($file, 'w');
        fwrite($fileObj, "\xEF\xBB\xBF"); // UTF-8 BOM
        fputcsv($fileObj, $title);
//        $list = $query->orderBy("created_at", "desc")->cursor();
        $counter = 0;
        foreach ($orders as $order) {
            fputcsv($fileObj, $callable($order));
            // 每5000行刷新一次文件缓冲
            if (++$counter % 5000 === 0) {
                fflush($fileObj);
//                ob_flush();
                flush();
                gc_collect_cycles();
                // 可选：记录进度
                Log::info("Processed {$counter} records");
            }
            unset($order);
        }
        fclose($fileObj);
    }


    //使用  大批量数据导出
    public function BigDataExportToExcel2(string $filename, array $s_array, array $tileArray = [], \Generator $dataGenerator = null)
    {

        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', "0");
        $fp = fopen($filename, 'a+');
        fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));//转码 防止乱码(比如微信昵称(乱七八糟的))
        if (!empty($s_array)) {
            fputcsv($fp, $s_array); // 写入可选的额外表头
        }
        fputcsv($fp, $tileArray);
        $index = 0;
        if ($dataGenerator == null) {
            throw new \Exception("迭代器为null,无法导出");
        }
//        foreach ($dataGenerator as $item) {
//            fputcsv($fp, $item);
//            // 关键优化：每次循环后手动释放内存
//            unset($item);
//            if ($index++ % 1000 === 0) { // 每1000行强制GC
//                gc_collect_cycles();
//            }
//        }
//        fclose($fp);
        $chunkSize = 10000;
        $buffer = [];
        $memoryStart = memory_get_usage();
        foreach ($dataGenerator as $row) {
            unset($csvRow);
            $buffer[] = array_values($row); // 重置数组索引保证CSV列对齐
            if (count($buffer) >= $chunkSize) {
                foreach ($buffer as $csvRow) {
                    fputcsv($fp, $csvRow);
                }
                $buffer = [];
                fflush($fp); // 强制刷新输出缓冲区
            }
            // 内存监控：每1000行检查一次
            if (++$index % 1000 === 0) {
                if (memory_get_peak_usage() > 450 * 1024 * 1024) {
                    throw new \Exception('Memory usage exceeds safe limit');
                }
            }
            if (memory_get_usage() - $memoryStart > 50 * 1024 * 1024) {
                gc_collect_cycles();
                $memoryStart = memory_get_usage();
            }
        }
        // 写入剩余数据
        if (!empty($buffer)) {
            foreach ($buffer as $csvRow) {
                fputcsv($fp, $csvRow);
            }
            unset($buffer);
        }
        fclose($fp);
    }


    public function exportToExcel(string $filename, array $s_array, array $tileArray = [], array $dataArray = []): bool
    {
        ini_set('memory_limit', '512M');
        ini_set('max_execution_time', "0");
        $fp = fopen($filename, 'a+');
        fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));//转码 防止乱码(比如微信昵称(乱七八糟的))
        if (!empty($s_array)) {
            fputcsv($fp, $s_array);
        }
//        fputcsv($fp, []);
        fputcsv($fp, $tileArray);
        $index = 0;
        foreach ($dataArray as $item) {
            $index++;
            fputcsv($fp, $item);
        }
        fclose($fp);
        return true;
    }

    public function uploadOss(string $targetFile, string $uploadPath): string
    {
        $AccessKeyId = env('ALIOSS_AccessKeyId');
        $AccessKeySecret = env('ALIOSS_AccessKeySecret');
        $endpoint = env('ALIOSS_endpoint');
        $bucket = env('ALIOSS_bucket');
        $content = file_get_contents($targetFile);
        $ossClient = new \OSS\OssClient($AccessKeyId, $AccessKeySecret, $endpoint);
        $result = $ossClient->putObject($bucket, 'wft/csv/' . date("Ymd") . "/" . $uploadPath, $content);
        return $result['oss-request-url'] ?? "";
    }

    public
    function export()
    {
//        $file_name = $users->name . $day . '.csv';
//        $path = BASE_PATH . "/uploads/csv";
//        if (!is_dir($path)) {
//            mkdir($path, 0777, true);
//        }
//        $file_path = $path . "/" . $file_name;
//        $fp = fopen($file_path, "a+"); // 生成文件
//        //写入excel
////        账单日期	代理商名称	门店名称	通道模式	通道名称	通道商户号	有效交易金额	基本费率	成本费率	返佣费率	返佣金额	税点	实际返佣
//        fputcsv($fp, ['账单日期', '代理商名称', '门店名称', "门店ID", '通道模式', '通道名称', '总交易金额', "有效交易金额", '退款', '手续费', '实收']);
//        foreach ($data as $k => $v) {
//            $model_name = "";
//            switch ((int)$v["receive_model"]) {
//                case 1:
//                    $model_name = "服务费模式";
//                    break;
//                case 2:
//                    $model_name = "代扣模式";
//                    break;
//                case 3:
//                    $model_name = "通道模式";
//                    break;
//                case 4:
//                    $model_name = "预充模式";
//                    break;
//            }
//            fputcsv($fp, [
//                $v["day"],
//                $v["agent_name"],
//                $v["store_name"],
//                "'" . $v["store_id"] . " ",
//                $model_name,
//                $v["ways_desc"],
//                $v["总金额"],//$item['bill_date'],
//                $v["总金额"] - $v["退款金额"],//$item['bill_date'],
//                $v["退款金额"],
//                $v["手续费"],//$item['bill_date'],
//                $v["实收"],//$item['bill_date'],
//            ]);
//        }
//        fclose($fp);
//        dd($data);
    }

}